import json
import logging
import random
import string
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from dj_youkou import constant
from user.models import User
from utils.captcha.captcha import Captcha
# from utils.captcha1.captcha import Captcha, captcha
from django.http import HttpResponse, JsonResponse
from utils.res_code.status_code import Code, error_map
from utils.res_code.status_json import status_json
# from utils.dysms_python.demo_sms_send import send_sms
from utils.yuntongxun.sms import send_sms

# Create your views here.

log_user = logging.getLogger('user')
from verification.forms import SmsVerificationForm, RetrieveVerificationForm


class ImageVerification(View):
    """
       用于图片验证的生成与缓存,图片验证码

       #1、创建视图类
       #2、从前端获取参数
       #3、参数校验
       #4、生成验证图片和图片验证码文本
       #5、图片验证码文本存入缓存redis
       #6、返回前端数据
    """

    def get(self, request, image_uuid):
        # 生成验证码文本和图片
        text, img = Captcha.gene_code()
        # tex, image = captcha.generate_captcha()

        image_code_key = 'img_{}'.format(image_uuid)
        # print(tex,image,image_code_key)

        # 创建redis connection
        redis_conn = get_redis_connection(alias='img_code')

        log_user.info('生成图片验证码code:{}'.format(text))
        # 存入redis数据库
        redis_conn.setex(name=image_code_key.encode('utf-8'), value=text.upper(),
                         time=constant.IMG_VERIFICATION_CODE_REDIS_EXPIRES)

        # 设置响应头
        response = HttpResponse(content=img, content_type='image/png')
        return response


class UserVerification(View):
    """
    用于验证用户注册时候是否已经注册过

    """

    def get(self, request, username):
        # 查询User数据库中username用户是否已经存在
        data = {'username': username,
                'count': User.objects.filter(username=username).count()}

        return status_json(data=data)


class SmsVerification(View):
    """
    用于注册时短信验证码，图片验证码，以及手机号是否注册的校验

    """

    # 生成一个随机数用于标记sms_flag

    def post(self, request):
        form = SmsVerificationForm(request.POST)
        # form表单校验完成后
        if form.is_valid():
            sms_captcha = ''.join([random.choice(string.digits) for _ in range(constant.SMS_VERIFICATION_CODE_NUM)])
            # 生成随机短信验证码
            tel = form.cleaned_data.get('tel')
            # 获取form表单校验之后的电话

            # ================此处为调用阿里云短信API接口===============================#
            """
            token = send_sms(phone_numbers=tel, sms_captcha=sms_captcha)
            # 调用阿里云短信服务接口，返回token
            token_dict = json.loads(token)
            # 将返回的token转化成字典
            if token_dict['Code'] == 'OK':
            # 验证码发送成功后存入redis数据库，同时存入一个标记60s的flag
            sms_code_key = 'sms_key_{}'.format(tel)
            sms_code_flag = 'sms_flag_{}'.format(tel)
            redis_conn = get_redis_connection(alias='sms_code')
            p1 = redis_conn.pipeline()
            try:
                # 捕获redis的pipeline运行时可能发生的错误
                p1.setex(name=sms_code_flag, value=1, time=60)
                p1.setex(name=sms_code_key, value=sms_captcha,
                         time=constant.SMS_VERIFICATION_CODE_REDIS_EXPIRES_FOR_ALI)
                p1.execute()
                # 让redis管道P1执行
                except Exception as e:
                log_user.debug('redis发生错误：{}'.format(e))
            return status_json(no=Code.UNKOWNERR, msg=error_map[Code.UNKOWNERR])
            else:
            log_user.info(msg='Register:手机{}验证码发送成功:{}'.format(tel, sms_captcha))
            return status_json(msg='手机验证码发送成功')
        else:
            # 当token返回的Code不是OK时 logging记录错误信息，并且返回数据给前端
            log_user.error('error:{}'.format(token_dict))
            return status_json(no=Code.SMSFAIL, msg=error_map[Code.SMSFAIL])
        
         """

            # ====================此处调用云通讯短信服务API接口===========================#
            # result = send_sms(phone_number=tel, sms_captcha=sms_captcha,
            #                   sms_expires=constant.SMS_VERIFICATION_CODE_REDIS_EXPIRES_FOR_YUNTX
            #                   )
            # 调用云通讯短信服务接口，返回result，result只有0和1两个结果
            result = 0
            if result == 0:

                # 验证码发送成功后存入redis数据库，同时存入一个标记60s的flag
                sms_code_key = 'sms_key_{}'.format(tel)
                sms_code_flag = 'sms_flag_{}'.format(tel)
                redis_conn = get_redis_connection(alias='sms_code')
                p1 = redis_conn.pipeline()
                # 创建redis管道，可以让多个任务同时进行
                try:
                    # 捕获redis的pipeline运行时可能发生的错误
                    p1.setex(name=sms_code_flag, value=1, time=60)
                    p1.setex(name=sms_code_key, value=sms_captcha,
                             time=constant.SMS_VERIFICATION_CODE_REDIS_EXPIRES_FOR_YUNTX * 60)
                    p1.execute()
                    # 让redis管道P1执行
                except Exception as e:
                    # 发生错误日志记录，并返回给前端相应错误信息
                    log_user.debug('Register:redis发生错误：{}'.format(e))
                    return status_json(no=Code.UNKOWNERR, msg=error_map[Code.UNKOWNERR])
                else:
                    # 未发生错误返回前端成功信息,并记录
                    log_user.info(msg='Register:手机{}验证码发送成功:{}'.format(tel, sms_captcha))
                    return status_json(msg='手机验证码发送成功')
            else:
                # 当result不是0时候 代表验证码发送失败，记录并返回数据
                log_user.error('Register:error:{}'.format("验证码发送失败{}，服务器错误").format(tel))
                return status_json(no=Code.SMSFAIL, msg=error_map[Code.SMSFAIL])
        else:
            # 当form表单校验未通过时候，返回前端具体error
            log_user.error('Register:验证码发送失败{}'.format(form.get_error))
            return status_json(no=Code.PARAMERR, msg=form.get_error)


class RetrieveVerification(View):
    """
    用于用户忘记密码时重置密码时获取短信验证码的的发送
    """

    def post(self, request):
        form = RetrieveVerificationForm(request.POST)
        # 对前端传来的数据进行form校验
        if form.is_valid():
            # 校验通过
            tel = form.cleaned_data.get('tel')
            sms_captcha = ''.join([random.choice(string.digits) for _ in range(0, constant.SMS_VERIFICATION_CODE_NUM)])
            # result = send_sms(phone_number=tel, sms_captcha=sms_captcha,
            #                   sms_expires=constant.SMS_VERIFICATION_CODE_REDIS_EXPIRES_FOR_YUNTX)
            # 发送短信验证码
            result = 0
            if result == 0:
                """
                验证码发送成功后存入数据库redis，并捕获redis管道的异常，最后返回json数据
                """
                sms_ret_key = 'sms_ret_{}'.format(tel)
                sms_ret_flag = 'sms_ref_flag_{}'.format(tel)
                redis_conn = get_redis_connection(alias='sms_code')
                p1 = redis_conn.pipeline()
                try:
                    p1.setex(name=sms_ret_key, value=sms_captcha,
                             time=constant.SMS_VERIFICATION_CODE_REDIS_EXPIRES_FOR_YUNTX * 60)
                    p1.setex(name=sms_ret_flag, value=1, time=60)
                    p1.execute()
                except Exception as e:
                    log_user.debug('Retrieve Password:redis发生错误：{}'.format(e))
                    return status_json(no=Code.UNKOWNERR, msg=error_map[Code.UNKOWNERR])
                else:
                    log_user.info(msg='Retrieve Password:手机验证码发送成功{}：{}'.format(tel, sms_captcha))
                    return status_json(msg='手机验证码发送成功')
            else:
                log_user.error('Retrieve Password:验证码发送失败{}>'.format(tel))
                return status_json(no=Code.SMSFAIL, msg=error_map[Code.SMSFAIL])
        else:
            log_user.error('Retrieve Password:验证码发送失败'.format(form.get_error))
            return status_json(no=Code.PARAMERR, msg=form.get_error)
